#include "EyerWASMIndexedDB.hpp"

#include "EyerWASMCommon/EyerWASMEventLoop.hpp"
#include "EyerWASMIndexedDB_OpenEvent.hpp"
#include "EyerWASMIndexedDB_PutEvent.hpp"
#include "EyerWASMIndexedDB_GetEvent.hpp"
#include "EyerWASMIndexedDB_CloseEvent.hpp"

namespace Eyer
{
    EyerWASMIndexedDB::EyerWASMIndexedDB(const std::string & _dbName)
        : dbName(_dbName)
    {

    }

    EyerWASMIndexedDB::~EyerWASMIndexedDB()
    {

    }

    int EyerWASMIndexedDB::Open()
    {
        std::shared_ptr<EyerWASMIndexedDB_OpenEvent> event = std::make_shared<EyerWASMIndexedDB_OpenEvent>(dbName);
        std::unique_lock<std::mutex> lck(event->mtx);
        EyerWASMEventLoop::GetInstance()->PutEvent(event);
        while(!event->isFinish()){
            event->cond.wait_for(lck, std::chrono::seconds(1));
        }
        indexedDBKey = event->GetIndexedDBKey();
        return 0;
    }

    int EyerWASMIndexedDB::Put(
            const std::string & key,
            const uint8_t * buf,
            size_t bufSize,
            int64_t contentLength,
            int64_t rangeLength)
    {
        std::shared_ptr<EyerWASMIndexedDB_PutEvent> event = std::make_shared<EyerWASMIndexedDB_PutEvent>(
                indexedDBKey,
                key,
                buf,
                bufSize,
                contentLength,
                rangeLength
                );
        std::unique_lock<std::mutex> lck(event->mtx);
        EyerWASMEventLoop::GetInstance()->PutEvent(event);
        while(!event->isFinish()){
            event->cond.wait_for(lck, std::chrono::seconds(1));
        }
        return 0;
    }

    int EyerWASMIndexedDB::Get(const std::string & key,
                               EyerWASMBuffer & buffer,
                               int64_t * contentLength,
                               int64_t * rangeLength)
    {
        std::shared_ptr<EyerWASMIndexedDB_GetEvent> event = std::make_shared<EyerWASMIndexedDB_GetEvent>(
                indexedDBKey,
                key
        );
        std::unique_lock<std::mutex> lck(event->mtx);
        EyerWASMEventLoop::GetInstance()->PutEvent(event);
        while(!event->isFinish()){
            event->cond.wait_for(lck, std::chrono::seconds(1));
        }

        if(!event->IsFound()){
            return -1;
        }

        buffer = event->GetBuffer();
        *contentLength = event->GetContentLength();
        *rangeLength = event->GetRangeLength();
        return 0;
    }

    int EyerWASMIndexedDB::Close()
    {
        std::shared_ptr<EyerWASMIndexedDB_CloseEvent> event = std::make_shared<EyerWASMIndexedDB_CloseEvent>(indexedDBKey);
        EyerWASMEventLoop::GetInstance()->PutEvent(event);
        std::unique_lock<std::mutex> lck(event->mtx);
        while(!event->isFinish()){
            event->cond.wait_for(lck, std::chrono::seconds(1));
        }
        return 0;
    }
}